package cn.csc.module.product.service.spu;

import cn.csc.framework.common.pojo.CommonResult;
import cn.csc.framework.common.pojo.PageResult;
import cn.csc.framework.common.util.number.ObjectNumberUtils;
import cn.csc.framework.common.util.validation.ValidationUtils;
import cn.csc.framework.mybatis.core.util.MyBatisUtils;
import cn.csc.framework.redisson.lock.util.RedisUtil;
import cn.csc.module.member.api.browsinghistory.ProductBrowsingHistoryApi;
import cn.csc.module.member.api.browsinghistory.dto.ProductBrowsingHistoryRespDTO;
import cn.csc.module.member.api.user.MemberUserApi;
import cn.csc.module.member.api.user.dto.MemberUserRespDTO;
import cn.csc.module.product.api.spu.dto.SpuDTO;
import cn.csc.module.product.config.CategoryProperties;
import cn.csc.module.product.constant.PlatformType;
import cn.csc.module.product.controller.admin.skuattrjson.vo.SkuAttrJsonSimpleReqVO;
import cn.csc.module.product.controller.admin.spu.vo.*;
import cn.csc.module.product.controller.app.spu.vo.*;
import cn.csc.module.product.convert.attr.AttrConvert;
import cn.csc.module.product.convert.attrvalue.AttrValueConvert;
import cn.csc.module.product.convert.category.CategoryConvert;
import cn.csc.module.product.convert.sku.SkuConvert;
import cn.csc.module.product.convert.spu.SpuConvert;
import cn.csc.module.product.dal.dataobject.attr.AttrDO;
import cn.csc.module.product.dal.dataobject.attrjson.AttrJsonDO;
import cn.csc.module.product.dal.dataobject.attrvalue.AttrValueDO;
import cn.csc.module.product.dal.dataobject.category.CategoryDO;
import cn.csc.module.product.dal.dataobject.extension.SpuExtensionDO;
import cn.csc.module.product.dal.dataobject.sku.SkuDO;
import cn.csc.module.product.dal.dataobject.skuattrjson.SkuAttrJsonDO;
import cn.csc.module.product.dal.dataobject.spu.SpuDO;
import cn.csc.module.product.dal.dataobject.spudetail.SpuDetailDO;
import cn.csc.module.product.dal.dataobject.stock.SkuStockDO;
import cn.csc.module.product.dal.dataobject.tagref.SpuTagReferenceDO;
import cn.csc.module.product.dal.mysql.attr.AttrMapper;
import cn.csc.module.product.dal.mysql.attrjson.AttrJsonMapper;
import cn.csc.module.product.dal.mysql.attrvalue.AttrValueMapper;
import cn.csc.module.product.dal.mysql.category.CategoryMapper;
import cn.csc.module.product.dal.mysql.extension.SpuExtensionMapper;
import cn.csc.module.product.dal.mysql.sku.SkuMapper;
import cn.csc.module.product.dal.mysql.skuattrjson.SkuAttrJsonMapper;
import cn.csc.module.product.dal.mysql.spu.SpuMapper;
import cn.csc.module.product.dal.mysql.spudetail.SpuDetailMapper;
import cn.csc.module.product.dal.mysql.stock.SkuStockMapper;
import cn.csc.module.product.dal.mysql.tagref.SpuTagReferenceMapper;
import cn.csc.module.product.validated.Verify1;
import cn.csc.module.shop.api.detail.ShopDetailApi;
import cn.csc.module.shop.api.detail.dto.ShopDetailRespDTO;
import cn.csc.module.shop.api.user.ShopUserApi;
import cn.csc.module.shop.api.user.dto.ShopUserRespDTO;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.base.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static cn.csc.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.csc.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.csc.module.product.enums.ErrorCodeConstants.*;
import static java.util.stream.Collectors.groupingBy;

/**
 * @author 云隐
 * @date 2024/11/22
 **/
@Slf4j
@Service
@Validated
public class SpuV2ServiceImpl implements SpuV2Service {

    @Resource
    private SpuMapper spuMapper;
    @Resource
    private AttrJsonMapper attrJsonMapper;
    @Resource
    private SkuAttrJsonMapper skuAttrJsonMapper;
    @Resource
    private SpuDetailMapper spuDetailMapper;
    @Resource
    private SkuMapper skuMapper;
    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private AttrMapper attrMapper;

    @Resource
    private AttrValueMapper attrValueMapper;

    @Resource
    private SpuTagReferenceMapper spuTagReferenceMapper;

    @Resource
    ShopDetailApi shopDetailApi;

    @Resource
    private ShopUserApi shopUserApi;
    @Resource
    private ProductBrowsingHistoryApi productBrowsingHistoryApi;
    @Resource
    private MemberUserApi memberUserApi;
    @Resource
    RedisUtil redisUtil;

    @Resource
    private CategoryProperties categoryProperties;

    @Resource
    SkuStockMapper skuStockMapper;
    @Resource
    SpuExtensionMapper spuExtensionMapper;


    @Transactional
    @Override
    public BigInteger createSpu(SpuCreateDataReqV2VO createReqVO) {

        if (createReqVO.getShopId() != null) {
            getShopDetail(createReqVO);
        } else {
            CommonResult<ShopUserRespDTO> shopUser = shopUserApi.getShopUser();
            if (shopUser.getCode() == 0) {
                ShopUserRespDTO shopUserRespDTO = shopUser.getData();
                if (shopUserRespDTO == null)
                    throw exception(SPU_SHOPNAME_NOT_EXISTS);
            } else
                throw exception(SPU_SHOPNAME_ERROR);

            createReqVO.setShopId(shopUser.getData().getShopId());
            getShopDetail(createReqVO);
            createReqVO.setPhone(shopUser.getData().getPhoneNumber());
        }

        createReqVO.getSkuAttr().forEach(s -> {
            ValidationUtils.validate(s);
            StringBuffer buffer = new StringBuffer();
            if (StringUtils.isNotBlank(s.getAttrName())) {
                buffer.append(s.getAttrName());
            }
            if (StringUtils.isNotBlank(s.getAttrName2())) {
                buffer.append("-").append(s.getAttrName2());
            }
            if (StringUtils.isNotBlank(s.getAttrName3())) {
                buffer.append("-").append(s.getAttrName3());
            }
            s.setSkuName(buffer.toString());
        });

        // 插入
        SpuDO spu = SpuConvert.INSTANCE.convertV2(createReqVO);
        spu.setMarketPriceFee(createReqVO.getPriceFee());
        if (spu.getVerifyStatus() != null && spu.getVerifyStatus() == 5) {
            spu.setOnlineTime(LocalDateTime.now());
            spu.setStatus(1);
        }

        if (createReqVO.getCzType() == 1)
            spu.setType(PlatformType.ORDINARY.getKey());
        else if (createReqVO.getCzType() == 2)
            spu.setType(PlatformType.SELECTPRODUCT.getKey());

        spuMapper.insert(spu);

        SpuDetailDO detailDO = new SpuDetailDO();
        detailDO.setId(spu.getId());
        detailDO.setDetail(createReqVO.getDetail());
        spuDetailMapper.insert(detailDO);

        AttrJsonDO jsonDO = new AttrJsonDO();
        jsonDO.setRuleAttrs(createReqVO.getRuleAttrs());
        jsonDO.setBasicAttrs(createReqVO.getBasicAttrs());
        jsonDO.setSpuId(spu.getId());
        attrJsonMapper.insert(jsonDO);

        List<SkuDO> skuList = SkuConvert.INSTANCE.convertList04(createReqVO.getSkuAttr());
        skuList.forEach(s -> {
            s.setStatus(1);//启用状态
            s.setSpuId(spu.getId());
            s.setPartyCode(ObjectNumberUtils.getOrder(""));
        });
        skuMapper.insertBatch(skuList);

        IntStream.range(0, skuList.size()).forEach(i -> {
            createReqVO.getSkuAttr().get(i).setSkuId(skuList.get(i).getId());
            createReqVO.getSkuAttr().get(i).setPartyCode(skuList.get(i).getPartyCode());
        });

        //新增商品SKU库存
        AtomicInteger totalNum = new AtomicInteger(0);
        List<SkuStockDO> stockList = new ArrayList<>();
        createReqVO.getSkuAttr().stream().forEach(s->{
            SkuStockDO  skuStockDO =new SkuStockDO();
            skuStockDO.setActualStock(s.getActualStock());
            skuStockDO.setStock(s.getActualStock());
            skuStockDO.setSkuId(s.getSkuId());
            stockList.add(skuStockDO);
            totalNum.getAndAdd(s.getActualStock());
        });
        skuStockMapper.insertBatch(stockList);
        //新增商品SPU库存
        SpuExtensionDO extensionDO = new SpuExtensionDO();
        extensionDO.setActualStock(totalNum.get());
        extensionDO.setSpuId(spu.getId());
        extensionDO.setStock(totalNum.get());
        extensionDO.setLockStock(0);
        extensionDO.setSaleNum(0);
        spuExtensionMapper.insert(extensionDO);

        SkuAttrJsonDO skuAttrJsonDO = new SkuAttrJsonDO();
        skuAttrJsonDO.setSpuId(spu.getId());
        skuAttrJsonDO.setAttrJson(createReqVO.getSkuAttr());
        skuAttrJsonMapper.insert(skuAttrJsonDO);

        // 保存基本属性
        List<AttrDO> attrList = AttrConvert.INSTANCE.convertList04(createReqVO.getBasicAttrs());
        if (createReqVO.getShopId() != null) {
            attrList.forEach(s -> {
                s.setShopId(createReqVO.getShopId());
            });
        }
        attrMapper.insertBatch(attrList);

        // 保存基本属性的值
        IntStream.range(0, attrList.size()).forEach(i -> createReqVO.getBasicAttrs().get(i).setId(attrList.get(i).getId()));
        List<AttrValueDO> attrValueList = new ArrayList<>();
        createReqVO.getBasicAttrs().forEach(s -> {
            AttrValueDO attrValueDO = AttrValueConvert.INSTANCE.convertList05(s);
            attrValueDO.setId(null);
            attrValueList.add(attrValueDO);
        });
        attrValueMapper.insertBatch(attrValueList);

        // 保存标签
        if (categoryProperties.getCategory().containsKey(createReqVO.getCategoryId())){
            String tagIds = categoryProperties.getCategory().get(createReqVO.getCategoryId());
            List<SpuTagReferenceDO> collect = Arrays.stream(tagIds.split(",")).map(id -> {
                SpuTagReferenceDO referenceDO = new SpuTagReferenceDO();
                referenceDO.setShopId(createReqVO.getShopId());
                referenceDO.setTagId(new BigInteger(id));
                referenceDO.setSpuId(spu.getId());
                return referenceDO;
            }).collect(Collectors.toList());
            spuTagReferenceMapper.insertBatch(collect);
        }

        return spu.getId();
    }

    private void getShopDetail(SpuCreateDataReqV2VO createReqVO) {
        CommonResult<ShopDetailRespDTO> result = shopDetailApi.getShopDetail(createReqVO.getShopId());
        if (result.getCode() == 0) {
            ShopDetailRespDTO dto = result.getData();
            if (dto == null) {
                throw exception(SPU_SHOPNAME_NOT_EXISTS);
            }
            createReqVO.setShopName(dto.getShopName());
            createReqVO.setPhone(dto.getPhoneNumber());
        } else {
            throw exception(SPU_SHOPNAME_ERROR);
        }
    }

    //还是怕有重复的信息，目前暂不使用
    private String handleSkuCode(int index, BigInteger productId) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        StringBuilder sb = new StringBuilder();
        //日期
        sb.append(sdf.format(new Date()));
        //四位商品id
        sb.append(String.format("%04d", productId));
        //三位索引id
        sb.append(String.format("%03d", index + 1));
        return sb.toString();
    }

    @Transactional
    @Override
    public void updateSpu(SpuCreateDataReqV2VO createReqVO) {
        // 校验存在
        validateSpuVerifyStatus(createReqVO.getId());

        int count = categoryMapper.selectCountById(createReqVO.getCategoryId());
        if (count <= 0)
            throw exception(CATEGORY_NOT_EXISTS);

        // 更新
        SpuDO spu = SpuConvert.INSTANCE.convertV2(createReqVO);
        spu.setMarketPriceFee(spu.getPriceFee());
        spuMapper.updateById(spu);

        SpuDetailDO detailDO = new SpuDetailDO();
        detailDO.setId(spu.getId());
        detailDO.setDetail(createReqVO.getDetail());
        spuDetailMapper.updateById(detailDO);

        if (createReqVO.getSkuAttr() != null) {
            AtomicInteger totalNum = new AtomicInteger(0);
            createReqVO.getSkuAttr().forEach(s -> {
                ValidationUtils.validate(s);
                SkuDO skuDO = new SkuDO();
                skuDO.setImgUrl(s.getImgUrl());
                skuDO.setPriceFee(s.getPriceFee());
                skuDO.setShopPriceFee(s.getShopPriceFee());
                skuDO.setActualStock(s.getActualStock());
                skuMapper.updateSku(skuDO, s.getSkuId());
                //修改库存
                skuStockMapper.updateStockNumber(s.getSkuId(),s.getActualStock());
                totalNum.getAndAdd(s.getActualStock());
            });
            //直接替换商品库存
           spuExtensionMapper.replaceStock(spu.getId(),totalNum.get());

            SkuAttrJsonDO skuJsonDO = skuAttrJsonMapper.selectOneDO(spu.getId());
            SkuAttrJsonDO skuAttrJsonDO = new SkuAttrJsonDO();
            skuAttrJsonDO.setAttrJson(createReqVO.getSkuAttr());
            if (skuJsonDO == null) {
                skuAttrJsonDO.setSpuId(spu.getId());
                skuAttrJsonMapper.insert(skuAttrJsonDO);
            } else {
                skuAttrJsonMapper.updateSkuAttrJson(spu.getId(), skuAttrJsonDO);
            }
        }
    }

    @Override
    public void verifySpu(SpuUpdateReqV2VO updateReqVO) {
        SpuDO spuDO = SpuConvert.INSTANCE.convertV2(updateReqVO);

        spuDO.setVerifyTime(LocalDateTime.now());
        if (spuDO.getVerifyStatus() == 10)
            spuDO.setStatus(1);
        else if (spuDO.getVerifyStatus() == 15)
            spuDO.setStatus(0);

        spuMapper.updateById(spuDO);
    }

    @Transactional
    @Override
    public void addShopSpuBatch(List<SpuShopDataReqV2VO> list) {
        list.stream().forEach(s -> {
            addShopSpu(s);
        });
    }

    @Transactional
    @Override
    public void addShopSpu(SpuShopDataReqV2VO spuShopDataReqVO) {
        // 校验存在
        validateSpuExists(spuShopDataReqVO.getId());

        SpuDO spu = SpuConvert.INSTANCE.convertV2(spuShopDataReqVO);
        spu.setShopMarketPriceFee(spuShopDataReqVO.getShopPriceFee());
        spu.setHasShop(1);

        spuShopDataReqVO.getSkuAttr().stream().forEach(s -> {
            s.setHasShop(1);
            ValidationUtils.validate(s, Verify1.class);
            SkuDO skuDO = new SkuDO();
            skuDO.setShopPriceFee(s.getShopPriceFee());
            skuMapper.updateSku(skuDO, s.getSkuId());
        });
        // 更新
        spuMapper.updateById(spu);

        List<SkuDO> list = skuMapper.selectList(spu.getId());
        if (list.size() != spuShopDataReqVO.getSkuAttr().size()) {
            throw exception(SPU_SIZE_VERIFY);
        }

        SkuAttrJsonDO skuAttrJsonDO = new SkuAttrJsonDO();
        skuAttrJsonDO.setAttrJson(spuShopDataReqVO.getSkuAttr());
        skuAttrJsonMapper.updateSkuAttrJson(spu.getId(), skuAttrJsonDO);
    }

    @Transactional
    @Override
    public void updateShelf(SpuUpdateReqV2VO updateReqVO) {
        SpuDO updateObj = SpuConvert.INSTANCE.convertV2(updateReqVO);
        SpuDO spu = getSpu(updateReqVO.getId());
        if (updateReqVO.getVerifyStatus() == 10) {
            if (spu.getVerifyStatus() != 5) {
                throw exception(SPU_STATUS_VERIFY2);
            }

            int count = categoryMapper.selectCountById(spu.getCategoryId());
            if (count <= 0)
                throw exception(CATEGORY_NOT_EXISTS);

            updateObj.setStatus(1);
            updateObj.setVerifyTime(LocalDateTime.now());
        } else if (updateReqVO.getVerifyStatus() == 15) {
            if (spu.getVerifyStatus() != 5 && spu.getVerifyStatus() != 10) {
                throw exception(SPU_STATUS_VERIFY2);
            }
            updateObj.setStatus(0);
        } else {
            throw exception(SPU_STATUS_VERIFY2);
        }

        List<String> categoryIds = Arrays.asList(spu.getCategoryLevel().split(","));
        spuMapper.updateById(updateObj);
        String num = "";
        if (updateReqVO.getVerifyStatus() == 10 && spu.getVerifyStatus() == 5) {
            num = "+1";
            categoryMapper.updateProductNum(categoryIds, num);
        } else if (updateReqVO.getVerifyStatus() == 15 && spu.getVerifyStatus() == 10) {
            num = "-1";
            categoryMapper.updateProductNum(categoryIds, num);
        }
    }

    @Override
    public void onShelf(SpuUpdateReqV2VO updateReqVO) {
        SpuDO updateObj = SpuConvert.INSTANCE.convertV2(updateReqVO);
        SpuDO spu = getSpu(updateReqVO.getId());
        if (updateReqVO.getVerifyStatus() == 5) {
            if (spu.getVerifyStatus() != 0 && spu.getVerifyStatus() != 15) {
                throw exception(SPU_STATUS_VERIFY2);
            }
            int count = categoryMapper.selectCountById(spu.getCategoryId());
            if (count <= 0)
                throw exception(CATEGORY_NOT_EXISTS);

            updateObj.setStatus(0);
            updateObj.setOnlineTime(LocalDateTime.now());
        } else if (updateReqVO.getVerifyStatus() == 0) {
            updateObj.setStatus(0);
        } else {
            throw exception(SPU_STATUS_VERIFY2);
        }
        spuMapper.updateById(updateObj);

        List<String> categoryIds = Arrays.asList(spu.getCategoryLevel().split(","));
        if (updateReqVO.getVerifyStatus() == 0 && spu.getVerifyStatus() == 10) {
            String num = "-1";
            categoryMapper.updateProductNum(categoryIds, num);
        }
    }

    @Transactional
    @Override
    public void deleteSpu(BigInteger id) {
        // 校验存在
        validateSpuVerifyStatus(id);
        //删除清楚类目下的商品
        SpuDO spu = spuMapper.selectById(id);
        if (spu.getVerifyStatus() == 10) {
            String num = "-1";
            List<String> categoryIds = Arrays.asList(spu.getCategoryLevel().split(","));
            categoryMapper.updateProductNum(categoryIds, num);
        }
        // 删除
        spuMapper.deleteById(id);
        spuDetailMapper.deleteById(id);
        attrJsonMapper.delAttrJson(id);
        skuAttrJsonMapper.delSkuAttrJson(id);
    }

    private void validateSpuExists(BigInteger id) {
        if (spuMapper.selectById(id) == null) {
            throw exception(SPU_NOT_EXISTS);
        }
    }

    private void validateSpuVerifyStatus(BigInteger id) {
        SpuDO spuDO = spuMapper.selectById(id);
        if (spuDO == null) {
            throw exception(SPU_NOT_EXISTS);
        }
        if (spuDO.getVerifyStatus() != 0 && spuDO.getVerifyStatus() != 15)
            throw exception(SPU_STATUS_VERIFY);
    }

    @Override
    public SpuDataRespV2VO getSpuAppDetail(BigInteger id) {
        SpuDO spuDO = spuMapper.getSpu(id);
        if (spuDO == null)
            throw exception(SPU_NOT_EXISTS);

        SpuDataRespV2VO respVO = SpuConvert.INSTANCE.convertDataV2(spuDO);

        SpuDetailDO detailDO = spuDetailMapper.selectById(id);
        if (detailDO != null) {
            respVO.setDetail(detailDO.getDetail());
            respVO.setDetailImg(detailDO.getDetailImg());
        }

        AttrJsonDO attrJsonDO = attrJsonMapper.selectOneDO(id);
        Optional.ofNullable(attrJsonDO).ifPresent(s -> respVO.setBasicAttrs(attrJsonDO.getBasicAttrs()));
        Optional.ofNullable(attrJsonDO).ifPresent(s -> respVO.setRuleAttrs(attrJsonDO.getRuleAttrs()));

        SkuAttrJsonDO skuAttrJsonDO = skuAttrJsonMapper.selectOneDO(id);
        skuAttrJsonDO.getAttrJson().forEach(s->{
            SkuStockDO skuStockDO = skuStockMapper.selectBySkuId(s.getSkuId());
            s.setActualStock(skuStockDO.getActualStock());
        });
        //Optional.ofNullable(skuAttrJsonDO).ifPresent(s -> respVO.setSkuAttr(s.getAttrJson().stream().filter(t-> t.getActualStock().intValue() > 0).collect(Collectors.toList())));
        Optional.ofNullable(skuAttrJsonDO).ifPresent(s -> respVO.setSkuAttr(skuAttrJsonDO.getAttrJson()));
        return respVO;
    }

    @Override
    public SpuDO getSpu(BigInteger id) {
        return spuMapper.selectById(id);
    }

    @Override
    public List<SpuDO> getSpuList(Collection<BigInteger> ids) {
        return spuMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<SpuDO> getSpuPage(SpuPageReqV2VO pageReqVO) {
        return spuMapper.selectPageV2(pageReqVO);
    }

    @Override
    public PageResult<SpuDO> selectPageExamine(SpuPageReqV2VO pageReqVO) {
        List<String> verifyStatusList = new ArrayList<>();
        if (pageReqVO.getVerifyStatus() != null) {
            verifyStatusList.add(String.valueOf(pageReqVO.getVerifyStatus()));
            if (pageReqVO.getVerifyStatus() == 0)
                verifyStatusList.add("15");
        } else {
            verifyStatusList.add("5");
            verifyStatusList.add("10");
        }
        pageReqVO.setStatusList(verifyStatusList);
        return spuMapper.selectPageByOnLineTimeV2Desc(pageReqVO);
    }

    @Override
    public PageResult<SpuDO> selectPageByOnLineTimeDesc(SpuPageReqV2VO pageReqVO) {
        List<String> verifyStatusList = new ArrayList<>();
        if (pageReqVO.getVerifyStatus() != null) {
            verifyStatusList.add(String.valueOf(pageReqVO.getVerifyStatus()));
            if (pageReqVO.getVerifyStatus() == 0)
                verifyStatusList.add("15");
        }
        pageReqVO.setStatusList(verifyStatusList);
        CommonResult<ShopUserRespDTO> shopUser = shopUserApi.getShopUser();
        if (shopUser.getCode() == 0) {
            ShopUserRespDTO shopUserRespDTO = shopUser.getData();
            if (shopUserRespDTO != null && shopUserRespDTO.getShopId() != null)
                pageReqVO.setShopId(shopUser.getData().getShopId());
        }
        return spuMapper.selectPageByOnLineTimeV2Desc(pageReqVO);
    }

    @Override
    public PageResult<SpuDO> getSpuPageSingle(SpuPageReqV2VO pageReqVO) {
        return spuMapper.selectPageSingleV2(pageReqVO);
    }

    @Override
    public List<SpuDO> getSpuList(SpuExportReqV2VO exportReqVO) {
        CommonResult<ShopUserRespDTO> shopUser = shopUserApi.getShopUser();
        if (shopUser.getCode() == 0) {
            ShopUserRespDTO shopUserRespDTO = shopUser.getData();
            if (shopUserRespDTO != null && shopUserRespDTO.getShopId() != null)
                exportReqVO.setShopId(shopUser.getData().getShopId());
        }
        return spuMapper.selectListV2(exportReqVO);
    }

    @Override
    public Long selectOKSpuNum(BigInteger shopId) {
        SpuDTO spuDTO = new SpuDTO();
        spuDTO.setShopId(shopId);
        spuDTO.setVerifyStatus(10);
        return spuMapper.selectOKSpuNum(spuDTO);
    }

    @Override
    public SpuDataRespV2VO getSpuById(BigInteger id) {
        SpuDO spuDO = getSpu(id);
        if (spuDO == null)
            throw exception(SPU_NOT_EXISTS);

        SpuDataRespV2VO respVO = SpuConvert.INSTANCE.convertDataV2(spuDO);

        SpuDetailDO detailDO = spuDetailMapper.selectById(id);
        if (detailDO != null) {
            respVO.setDetail(detailDO.getDetail());
            respVO.setDetailImg(detailDO.getDetailImg());
        }

        AttrJsonDO attrJsonDO = attrJsonMapper.selectOneDO(id);
        Optional.ofNullable(attrJsonDO).ifPresent(s -> respVO.setBasicAttrs(attrJsonDO.getBasicAttrs()));
        Optional.ofNullable(attrJsonDO).ifPresent(s -> respVO.setRuleAttrs(attrJsonDO.getRuleAttrs()));

        SkuAttrJsonDO skuAttrJsonDO = skuAttrJsonMapper.selectOneDO(id);
        skuAttrJsonDO.getAttrJson().forEach(s->{
            SkuStockDO skuStockDO = skuStockMapper.selectBySkuId(s.getSkuId());
            s.setActualStock(skuStockDO.getActualStock());
        });
        Optional.ofNullable(skuAttrJsonDO).ifPresent(s -> respVO.setSkuAttr(skuAttrJsonDO.getAttrJson()));
        return respVO;
    }

    /**
     * 根据店铺id列表查询各店铺审核通过的商品有多少个
     *
     * @param list 店铺id列表
     * @return
     */
    @Override
    public Map<String, Object> getSkuCountByShopIds(List<BigInteger> list) {
        List<Map<String, Object>> mapList = spuMapper.selectSkuCountByShopIds(10, list);
        Map<String, Object> collect = mapList.stream()
                .collect(Collectors.toMap(map -> map.get("shopId").toString(), map -> map.get("count"), (m1, m2) -> m2));
        return collect;
    }

    @Override
    public PageResult<AppSpuRespVO> searchAppProduct(AppSpuSearchPageReqVO reqVO) {
        IPage<AppSpuRespVO> mpPage = MyBatisUtils.buildPage(reqVO);
        spuMapper.searchAppProduct(reqVO, mpPage);
        long totalPage;
        if (mpPage.getTotal() > 0) {
            if (mpPage.getTotal() % reqVO.getPageSize() <= 0)
                totalPage = mpPage.getTotal() / reqVO.getPageSize();
            else
                totalPage = (mpPage.getTotal() / reqVO.getPageSize()) + 1;

            if ( totalPage< Long.valueOf(reqVO.getPageNo().toString()))
                 mpPage.setRecords(null);

        } else {
            return new PageResult<>();
        }
        return new PageResult<>(mpPage.getRecords(), mpPage.getTotal(), totalPage);
    }

    @Override
    public List<AppSpuHighRespVO> getHighProudct() {
        //查询商品最多的5个三级分类信息
        List<CategoryDO> list = categoryMapper.listHighCategory();
        if (list != null && list.size() > 1) {
            List<AppSpuHighRespVO> respList = CategoryConvert.INSTANCE.convertList04(list);
            respList.forEach(s -> {
                s.setProductData(spuMapper.selectHighByCategoryId(s.getId()));
            });
            return respList;
        }
        return new ArrayList<>();
    }

    @Override
    public List<AppSpuRespVO> selectIndexNew(AppSpuCreateReqVO reqVO) {
        List<SpuDO> list = spuMapper.selectLastNew(reqVO);
        Random random = new Random();
        List<SpuDO> newList = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            int num = random.nextInt(list.size());
            newList.add(list.get(num));
            list.remove(num);
        }
        return SpuConvert.INSTANCE.convertList3(newList);
    }

    @Override
    public List<AppCategoryRespVO> selectLastNew(AppSpuCreateReqVO reqVO) {
        List<SpuDO> list = spuMapper.selectLastNew(reqVO);

        Set<BigInteger> ids = new HashSet<>();
        //以商品排序的方式作为类目排序方式
        List<BigInteger> idList = new ArrayList<>();
        list.forEach(s -> {
            //二级类目分类
            String categroyId = s.getCategoryLevel().split(",")[1];
            s.setCategoryLevel(categroyId);
            BigInteger id = new BigInteger(categroyId);
            ids.add(id);
            if (!idList.contains(id))
                idList.add(id);
        });

        List<CategoryDO> categorys = categoryMapper.getListByCategoryIds(ids);
        List<AppCategoryRespVO> categoryList = CategoryConvert.INSTANCE.convertList05(categorys);
        Map<String, List<SpuDO>> map = list.stream().collect(groupingBy(item ->
                item.getCategoryLevel()
        ));

        Map<BigInteger, AppCategoryRespVO> categoryMap = categoryList.stream().collect(Collectors.toMap(AppCategoryRespVO::getId, Function.identity()));

        List<AppCategoryRespVO> respVO = new ArrayList<>();
        Long userId = getLoginUserId();
        CommonResult<MemberUserRespDTO> result = memberUserApi.getUser(userId);
        idList.forEach(s -> {
            AppCategoryRespVO appCategoryRespVO = categoryMap.get(s);
            List<SpuDO> spu = map.get(s.toString());
            List<AppSpuRespVO> spuList = SpuConvert.INSTANCE.convertList3(spu);

            Optional.ofNullable(spuList).ifPresent(x -> {
                x.forEach(t -> {
                    if (userId != null) {
                        if (result.getCode() == 0) {
                            //用戶表type: 5和15都代表采购商
                            if (result.getData() != null && (result.getData().getType() == 5 || result.getData().getType() == 15)) {
                                t.setMarketPriceFee(t.getShopPriceFee());
                            } else {
                                t.setMarketPriceFee(t.getPriceFee());
                            }
                        }else{
                            t.setMarketPriceFee(t.getPriceFee());
                        }
                    } else {
                        t.setMarketPriceFee(t.getPriceFee());
                    }
                });
            });
            if (spuList.size() >= 2) {
                if (spuList.size() > 6)
                    appCategoryRespVO.setData(spuList.stream().limit(6).collect(Collectors.toList()));
                else
                    appCategoryRespVO.setData(spuList);

                respVO.add(appCategoryRespVO);
            }
        });

        return respVO;
    }

    @Override
    public void addFraction(SpuDataRespV2VO spuDataRespV2VO) {
        spuMapper.addFraction(spuDataRespV2VO);
    }

    @Override
    public void discountedProduct() {
        CommonResult<List<ProductBrowsingHistoryRespDTO>> result = productBrowsingHistoryApi.getProductList();
        if (result.getCode() == 0) {
            if (result.getData() != null && !result.getData().isEmpty()) {
                List<BigInteger> ids = result.getData().stream().map(s -> s.getSpuId()).collect(Collectors.toList());
                List<SpuDO> list = spuMapper.selectListByIds(ids);
                list.forEach(s -> {
                    s.setSeq(Integer.parseInt(RandomUtil.randomNumbers(6)));
                });

                List<SpuDO> sortList = list.stream().sorted(Comparator.comparing(j -> j.getSeq(), Comparator.reverseOrder())).collect(Collectors.toList());

                //取出价格小于100元
                List<SpuDO> priceMInList = sortList.stream().filter(s -> s.getPriceFee().compareTo(new BigDecimal(100)) < 0).collect(Collectors.toList());

                //取出价格大于100元
                List<SpuDO> priceMaxList = sortList.stream().filter(s -> s.getPriceFee().compareTo(new BigDecimal(100)) > 0).collect(Collectors.toList());


                List<SpuDO> resultList = new ArrayList<>();
                if (priceMInList != null && !priceMInList.isEmpty() && priceMInList.size() > 15) {
                    List<SpuDO> resList = priceMInList.stream().limit(15).collect(Collectors.toList());
                    resultList.addAll(resList);
                } else
                    resultList.addAll(priceMInList);


                if (priceMaxList != null && !priceMaxList.isEmpty() && priceMaxList.size() > 4) {
                    List<SpuDO> resList = priceMaxList.stream().limit(4).collect(Collectors.toList());
                    resultList.addAll(resList);
                } else
                    resultList.addAll(priceMaxList);

                String idArray = Joiner.on(",").join(resultList.stream().map(s -> s.getId()).collect(Collectors.toList()));

                if (StringUtils.isNotBlank(idArray)) {
                    redisUtil.delete("discounted");
                    boolean flag = redisUtil.set("discounted", idArray);
                    if (!flag) {
                        log.error("=========限时优惠商品进入缓存失败=========");
                    }
                }
            }
        }
    }

    @Override
    public List<SpuDO> selectdiscountedProduct() {
        Object obj = redisUtil.get("discounted");
        List<SpuDO> list = new ArrayList<>();
        if (obj != null && StringUtils.isNotBlank(obj.toString())) {
            List<BigInteger> ids = new ArrayList<>();
            String[] strs = obj.toString().split(",");
            for (String str : strs) {
                ids.add(new BigInteger(str));
            }
            String idArray = Joiner.on(",").join(ids);
            log.info("===请求获取到ID==:{}",idArray);
            list = spuMapper.selectListByIds(ids);
        }
        return list;
    }

    @Transactional
    @Override
    public void updateSkuAttrJsonBySpuId(SkuAttrJsonSimpleReqVO reqVO) {
        SkuAttrJsonDO skuAttrJsonDO = new SkuAttrJsonDO();
        skuAttrJsonDO.setSpuId(reqVO.getSpuId());
        skuAttrJsonDO.setAttrJson(reqVO.getAttrJson());
        skuAttrJsonMapper.updateSkuAttrJson(reqVO.getSpuId(), skuAttrJsonDO);
        if (reqVO.getAttrJson() != null) {
            reqVO.getAttrJson().forEach(s -> {
                SkuDO skuDO = new SkuDO();
                skuDO.setPriceFee(s.getPriceFee());
                skuDO.setShopPriceFee(s.getShopPriceFee());
                skuDO.setActualStock(s.getActualStock());
                skuMapper.updateSku(skuDO, s.getSkuId());
                //修改库存
                skuStockMapper.updateStockNumber(s.getSkuId(), s.getActualStock());
            });
        }
    }
}
